<!-- **
    * @description ECharts 图表组件
** -->
<!-- **
    * @use 无需引入直接使用 <yfn-chart :title="" :data="[]" :option="{}"></yfn-chart>
    * @use 示例
    *            <yfn-chart title="图表标题" :data="[10, 200, 600]" :x-data="['x1', 'x2', 'x3']" /> （简易版）
    *         或 <yfn-chart title="图表标题" :data="[10, 200, 600]" :x-data="['x1', 'x2', 'x3']" :data-option="{ type: 'line' }" />
    *         或 <yfn-chart title="图表标题" :data="[{ value: 10 }, { value: 200 }, { value: 600 }]" :x-data="['x1', 'x2', 'x3']" :data-option="{ type: 'line' }" />
    *         或 <yfn-chart :option="{ title: { text: '图表标题' }, yAxis: { type: 'value' }, xAxis: { type: 'category', data: ['x1', 'x2', 'x3'] }, series: [{ type: 'line', data: [10, 200, 600] }] }" />
    *         (以上示例中四种方式效果一致)
    * 示例 饼图  <yfn-chart title="图表标题" :data="[{ value: 1048, name: 'Search Engine' },{ value: 735, name: 'Direct' },{ value: 580, name: 'Email' }]" :data-option="{type: 'pie'}" :option="{tooltip: {trigger: 'item'}}"></yfn-chart>
    * 示例 地图  <yfn-chart :data="[{name: 'US', value: 33142}, {name: 'UK', value: 5690}]" :data-option="{type: 'map', map: 'World'}" @get-instance="getInstance" />
    ** -->
<!-- **
    * @params参数说明：
    * @params {option}                 图表配置项
    * @params {title}                  图表标题（简易配置），优先级低于 option.title 配置; [String/Number]
    * @params {x-data}                 x 轴数据（简易配置），优先级低于 option.xAxis.data; [Array]
    * @params {data}                   系列数据（简易配置），优先级低于 option.series.data，[Array]
    * @params {data-option}            系列配置项 option.series 中通用配置项（简易配置），优先级低于 option.series 内配置; [Object]
    * @params {theme}                  图表主题，默认 - ，可选 dark 深色模式; [String]
    * @params {width}                  图表宽度，默认 100%
    * @params {height}                 图表高度，默认 300px
    * @params {style}                  图表样式 [Object]
    * @params {...}                    继承 Echarts 原生属性/方法/事件，更多查看 https://echarts.apache.org/zh/api.html#echarts
** -->
<!-- **
    * @params {option}                图表配置项
    * @params {option.title}          标题,优先级高于 title; {text: 标题, show: 是否显示标题, subText: 副标题, ...}
    * @params {option.legend}         图例，展现不同系列的标记(symbol)，颜色和名字
    * @params {option.xAxis}          x 轴，option.xAxis.data 优先级高于 x-data; {type: '坐标轴类型', data: []}
    * @params {option.yAxis}          y 轴, {type: 坐标轴数据类型, ...} -> type: ['category', 'value', 'time', 'log'], option.yAxis.type 默认为 value
    * @params {option.tooltip}        提示框
    * @params {option.series}         系列配置项，[*注：option.series 内参数优先级高于 dataOption / option.series.data 优先级高于 data]
    * @params {...}                   继承 Echarts 原生属性/方法/事件，更多参数查看 https://echarts.apache.org/zh/option.html
** -->
<!-- **
    * @params{option.series}          系列配置项，[*注：option.series 内参数优先级高于 dataOption]
    * @params{option.series.type}     图表类型，默认 line; 可选值 line 折线图、pie 饼图/环图、bar 折线图、map 地图等
    * @params{option.series.data}     系列数据，[*注: option.series.data 优先级高于 data]
    * @params {...}                   继承 Echarts 中 series 原生属性，更多参数查看 https://echarts.apache.org/zh/option.html#series
  ** -->
<!-- **
    * @params {data}                   系列数据，[*注：优先级低于 option.series.data，[Array]]
                                       eg: 单系列 [1, 1, ...] or [{value: 1}, {value: 1}, ...]、多系列 [[1, 1, ...], [1, 1,..], ...] or [[{value: 1}, {value: 1}, ..], [{value: 1}, {value: 1}, ..], ..];
    * @params {data.value}             数据项的数值
    * @params {data.name}              数据项名称
    * @params {...}                    继承 Echarts 中 series.data 原生属性; 更多参数查看 https://echarts.apache.org/zh/option.html#series-line.data
** -->
<!-- **
    * @params {dataOption}            系列配置项 option.series 中通用配置项 [*注：优先级低于 option.series 系列数据内配置]
    * @params {dataOption.type}       图表类型，可选值 line 折线图、pie 饼图/环图、bar 折线图、map 地图等
    * @params {dataOption.name}       对应列内容的字段名
    * @params {dataOption.label}      图形上的文本标签， {color: '', show: true, ...}
    * @params {dataOption.map}        注册的地图名称，type = map 下生效，可选值 World 全球、AU、CA、DE、FR、UK、US
    * @params {...}                   继承 Echarts 中 series 原生属性/方法/事件，更多参数查看 https://echarts.apache.org/zh/option.html#series
** -->
<!-- **
    * @events事件：
    * @click                           点击事件
    * @highlight                       高亮事件
    * @get-instance                    获取实例
    * @{...}                           继承 Echarts 原生事件，更多事件查看 https://echarts.apache.org/zh/api.html#events
** -->
<template>
  <v-chart class="YfnChart" ref="YfnChart" :style="setStyle()" :option="setOption()" />
</template>

<script lang="ts" setup>
  import { defineProps, getCurrentInstance } from 'vue'
  import * as echarts from 'echarts/core'
  import VChart from 'vue-echarts'
  // 引入图表，图表后缀都为 Chart
  import { BarChart, LineChart, PieChart, RadarChart, PictorialBarChart, FunnelChart, MapChart } from 'echarts/charts'
  // 引入提示框，标题，直角坐标系，数据集，内置数据转换器组件，组件后缀都为 Component
  import { TitleComponent, TooltipComponent, GridComponent, LegendComponent, DatasetComponent, TransformComponent, ToolboxComponent, GeoComponent, VisualMapComponent } from 'echarts/components'
  // 引入标签自动布局、全局过渡动画等特性
  import { LabelLayout, UniversalTransition } from 'echarts/features'
  import { CanvasRenderer } from 'echarts/renderers'
  // 地图数据
  import World from './json/world.json'
  import AU from './json/AU.json'
  import CA from './json/CA.json'
  import DE from './json/DE.json'
  import FR from './json/FR.json'
  import UK from './json/UK.json'
  import US from './json/US.json'

  echarts.use([BarChart, LineChart, PieChart, RadarChart, PictorialBarChart, FunnelChart, MapChart, TitleComponent, TooltipComponent, GridComponent, LegendComponent, DatasetComponent, TransformComponent, ToolboxComponent, LabelLayout, UniversalTransition, CanvasRenderer, GeoComponent, VisualMapComponent])

  /* props */
  const props: any = defineProps({
    title: [String, Number],
    width: String,
    height: String,
    style: Object,
    xData: Array,
    data: Array,
    dataOption: Object,
    option: {
      type: Object,
      default: () => {
        return {}
      },
    },
  })
  /* proxy */
  const { proxy } = getCurrentInstance() as any
  /* emit */
  const emit = defineEmits(['get-instance'])
  /* fn */
  // data 数据设置
  const setOption = () => {
    // 设置标题
    const title = setTitle()
    // 设置 xAxis、yAxis
    const axis = setAxis()
    // 设置 series
    const series = setSeries()
    // 设置map
    const mapOption = setMap(series)
    // const mapOption = setMap()
    const option = {
      ...mapOption,
      ...props.option,
      ...axis,
      ...series,
      title,
    }
    emit('get-instance', proxy)
    return option
  }
  const setStyle = () => {
    // 设置 style
    const style = props.style
    return {
      width: props.width || '100%',
      height: props.height || '300px',
      ...style,
    }
  }
  const setTitle = () => {
    // 设置标题
    const option: any = props.option
    return {
      text: props.title || '',
      ...option.title,
    }
  }
  const setAxis = () => {
    // 设置 xAxis、yAxis
    const option: any = props.option
    const hasXAxis = props.xData || option.xAxis
    const hasYAxis = hasXAxis || option.yAxis
    let xAxis: any = {}
    let yAxis: any = {}
    let mergeAxis: any = {}
    // xAxis
    if (hasXAxis) {
      xAxis = {
        type: 'category',
        data: props.xData || [],
        ...option.xAxis,
      }
      mergeAxis.xAxis = xAxis
    }
    // yAxis
    if (hasYAxis) {
      yAxis = {
        type: 'value',
        ...option.yAxis,
      }
      mergeAxis.yAxis = yAxis
    }
    return mergeAxis
  }
  const setSeries = () => {
    // 设置 series
    const option: any = props.option
    const series: any = option.series || []
    const firstSeries = series[0] || {}
    const hasSeries = !!series.length
    const dataOption = props.dataOption || {}
    const defaultSeriesOption = { type: 'line' }
    // series.data 数据
    const data = props.data || []
    const hasPropsData = !!data.length
    const hasArray = Object.prototype.toString.call(data[0]) === '[object Array]'
    const dataArr = hasArray || !hasPropsData ? data : [data]
    // 地图默认配置项
    const mapType = firstSeries.map || dataOption.map
    const mapSeriesOption = setMapSeriesOption(mapType)
    // series 数据
    let seriesArr: any = []
    if (!hasSeries) {
      dataArr.forEach((p: any) => {
        seriesArr.push({
          ...defaultSeriesOption,
          ...mapSeriesOption,
          ...dataOption,
          data: p,
        })
      })
    } else {
      series.forEach((p: any, i: number) => {
        seriesArr.push({
          ...defaultSeriesOption,
          ...mapSeriesOption,
          ...dataOption,
          ...p,
          data: p.data || dataArr[i],
        })
      })
    }
    const seriesResult = !!seriesArr.length ? { series: seriesArr } : {}
    return seriesResult
  }
  const setMap = (obj: any) => {
    // 设置 map
    const series = obj.series || []
    const firstSeries: any = series[0] || {}
    const type = firstSeries.type
    const mapType = firstSeries.map
    if (type != 'map') return {}
    // map 配置项
    const maxNum = Math.ceil(
      //获取最大值
      Math.max.apply(
        null,
        firstSeries.data.map((p: any) => p.value)
      ) / 4
    )
    const pieces = [
      // 设置图例
      { min: maxNum * 3, max: maxNum * 4, color: '#3267D7' },
      { min: maxNum * 2, max: maxNum * 3, color: '#1681F0' },
      { min: maxNum, max: maxNum * 2, color: '#41ABFF' },
      { min: 0, max: maxNum, color: '#A3CBFF' },
      { value: 0, label: '无数据', color: '#EDEDED' },
    ]
    const mapOption = {
      grid: {
        right: '8%',
      },
      visualMap: {
        // 分区域着色
        // min: 0,
        // max: 2200000,
        type: 'piecewise',
        // splitNumber:5, // 对于连续型数据，自动平均切分成几段。默认为5段
        hoverLink: false,
        itemWidth: 12, // 图形的宽度，即长条的宽度。
        itemHeight: 12, // 图形的高度，即长条的高度。
        pieces: pieces, // 分段式映射
        textStyle: {
          // 文本样式
          color: '#777F86',
        },
        bottom: 15, // 组件离容器下侧的距离
      },
      nameMap: {},
      geo: {
        map: mapType,
        aspectScale: 1, // 长宽比
        zoom: 1.05,
        roam: false,
        emphasis: {
          label: {
            show: true,
          },
          itemStyle: {
            color: null,
          },
        },
        select: {
          // 地图选中区域样式
          label: {
            show: false,
          },
          itemStyle: {
            // 地图点击后样式
            color: null,
          },
        },
        data: firstSeries.data,
      },
      zlevel: 999,
    }
    // map注册
    const mapJson = { World, AU, CA, DE, FR, UK, US }
    const usCity = {
      Alaska: { left: -131, top: 25, width: 15 }, // 把阿拉斯加移到美国主大陆左下方
      Hawaii: { left: -110, top: 28, width: 5 }, // 夏威夷
      'Puerto Rico': { left: -76, top: 26, width: 2 }, // 波多黎各
    }
    const hasUs = mapType == 'US'
    const config = hasUs ? usCity : {}
    echarts.registerMap(mapType, mapJson[mapType], config)
    return mapOption
  }
  const setMapSeriesOption = (type: any) => {
    if (!type) return {}
    return {
      roam: false,
      zoom: 1.05,
      map: type,
      silent: true,
      geoIndex: 0,
      itemStyle: {
        areaColor: '#B2CAE0',
        borderColor: '#fff',
        borderWidth: 1,
      },
      emphasis: {
        itemStyle: {
          areaColor: '#FFAE00',
        },
        label: {
          show: false,
        },
      },
    }
  }
</script>

<style scoped lang="less"></style>
